using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Silverlight.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace IsoStorageFacade_WP7_Tests
{
    [TestClass]
    public class Test_Sys_IO_PSFileInfo
    {
        private const string RootFolder = @"\Isolated\";
        private const string TestLine1 = "this is a test";
        private const string TestLine2 = "Last Line";
        private string TestDir = "TestDir";
        private const string TestFile = "test.txt";
        private const string kTextReaderTestFile = "textReaderTest.txt";

        [TestInitialize]
        public void setup()
        {
            PSDirectory.SetCurrentDirectory(@"\");
            // create file
            using (var strm = PSFile.Create(RootFolder + TestFile))
            {
                strm.WriteByte(65);
                strm.Flush();
                strm.Close();
            }
            PSDirectory.CreateDirectory(RootFolder + TestDir);
            PSDirectory.CreateDirectory("zzzTest");
        }

        [TestCleanup]
        public void teardown()
        {
            PSDirectory.SetCurrentDirectory(@"\");
            PSFile.Delete(RootFolder + TestFile);
            PSDirectory.Delete("zzzTest");
            PSDirectory.Delete(RootFolder + TestDir);
        }

        [TestMethod]
        public void When_Using_Exists_Should_Determine_If_A_File_Actually_Exists()
        {
            Assert.IsTrue((new PSFileInfo(RootFolder + TestFile)).Exists, "Test Env Created File should return true for PSFileInfo.Exiss");

            Assert.IsFalse((new PSFileInfo("zzzz")).Exists, "non existent File should return false for PSFileInfo.Exists");

            PSDirectory.SetCurrentDirectory("zzzTest");
            Assert.IsFalse((new PSFileInfo(TestFile)).Exists, "Non existent file in Subdir should return false");
        }

        [TestMethod]
        public void When_FileLength_Should_Return_1_For_Our_Test_File()
        {
            Assert.IsTrue((new PSFileInfo(RootFolder + TestFile)).Length == 1, "Should return 1 byte as the length for our test file");
        }

        [TestMethod]
        public void Should_be_Able_To_Copy_and_Move_A_File()
        {
            try
            {
                var fi = (new PSFileInfo(RootFolder + TestFile));
                var fi2 = fi.CopyTo(RootFolder + "zzz" + TestFile);
                Assert.IsTrue(IsolatedStorageFile.GetUserStoreForApplication().FileExists(RootFolder + "zzz" + TestFile), "Copied File should exist");

                using (var strm = (IsolatedStorageFile.GetUserStoreForApplication().OpenFile(RootFolder + "zzz" + TestFile, FileMode.Open, FileAccess.Read, FileShare.Read)))
                {
                    var byt = strm.ReadByte();
                    Assert.AreEqual(65, byt, "Copied file should contain the same content as the original");
                }

                fi2.MoveTo(RootFolder + "aaa" + TestFile);
                Assert.IsFalse(IsolatedStorageFile.GetUserStoreForApplication().FileExists(RootFolder + "zzz" + TestFile), "moved source File should not exist");

                Assert.IsTrue(IsolatedStorageFile.GetUserStoreForApplication().FileExists(RootFolder + "aaa" + TestFile), "moved dest File should exist");
            }
            finally
            {
                if (IsolatedStorageFile.GetUserStoreForApplication().FileExists(RootFolder + "zzz" + TestFile))
                    IsolatedStorageFile.GetUserStoreForApplication().DeleteFile(RootFolder + "zzz" + TestFile);
                if (IsolatedStorageFile.GetUserStoreForApplication().FileExists(RootFolder + "aaa" + TestFile))
                    IsolatedStorageFile.GetUserStoreForApplication().DeleteFile(RootFolder + "aaa" + TestFile);
            }
        }

        [TestMethod]
        public void Test_Reading_A_File()
        {
            var fi = (new PSFileInfo(RootFolder + TestFile));
            using (var strm = fi.OpenText())
            {
                var readAll = strm.ReadToEnd();
                Assert.IsTrue((readAll ?? "").Trim().Length > 0, "ReadToEnd should return data in the string");
            }

            try
            {
                /// create new dummy file
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var strmW = new StreamWriter(store.CreateFile(RootFolder + kTextReaderTestFile)))
                    {
                        strmW.WriteLine(TestLine1);
                        strmW.Write(TestLine2);
                    }
                }
                fi = (new PSFileInfo(RootFolder + kTextReaderTestFile));
                using (var strm = fi.OpenText())
                {
                    var readLine = strm.ReadLine();
                    Assert.AreEqual(TestLine1, readLine, "1st ReadLine call should return first line");
                    readLine = strm.ReadLine();
                    Assert.AreEqual(TestLine2, readLine, "2nd ReadLine call should return firstsecond line");
                    Assert.IsTrue(strm.EndOfStream, "Should now be at the end of the file");
                }
                using (var strm = fi.OpenRead())
                {
                    var buffer = new byte[strm.Length + 1];
                    strm.Read(buffer, 0, buffer.Length);
                    Assert.IsNotNull(buffer, "Should have read data into the buffer");
                    Assert.IsNotNull(buffer[0], "Should have read data into the first position of the buffer");
                    Assert.IsNotNull(buffer[buffer.Length - 2], "Should have read data into the second to the last position of the buffer");
                    Assert.AreEqual(0, buffer[buffer.Length - 1], "Should not have read data into the last position of the buffer (byte should be 0)");
                }
            }
            finally
            {
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (store.FileExists(RootFolder + kTextReaderTestFile))
                        store.DeleteFile(RootFolder + kTextReaderTestFile);
                }
            }
        }

        [TestMethod]
        public void Test_Creating_A_File()
        {
            try
            {
                var fi = (new PSFileInfo(RootFolder + kTextReaderTestFile));
                using (var strmW = fi.CreateText())
                {
                    strmW.WriteLine(TestLine1);
                    strmW.Write(TestLine2);
                }
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var strmR = new StreamReader(store.OpenFile(RootFolder + kTextReaderTestFile, FileMode.Open, FileAccess.Read)))
                    {
                        var line = strmR.ReadLine();
                        Assert.AreEqual(TestLine1, line, "First line read back should match the line written");
                        line = strmR.ReadLine();
                        Assert.AreEqual(TestLine2, line, "Second line read back should match the line written");
                    }
                    if (store.FileExists(RootFolder + kTextReaderTestFile))
                        store.DeleteFile(RootFolder + kTextReaderTestFile);
                }
                PSDirectory.SetCurrentDirectory(RootFolder + TestDir);
                fi = (new PSFileInfo(kTextReaderTestFile));
                using (var strmW = fi.CreateText())
                {
                    strmW.WriteLine(TestLine1);
                    strmW.Write(TestLine2);
                }
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var strmR = new StreamReader(store.OpenFile(RootFolder + TestDir + @"\" + kTextReaderTestFile, FileMode.Open, FileAccess.Read)))
                    {
                        var line = strmR.ReadLine();
                        Assert.AreEqual(TestLine1, line, "First line read back should match the line written (after current dir set)");
                        line = strmR.ReadLine();
                        Assert.AreEqual(TestLine2, line, "Second line read back should match the line written (after current dir set)");
                    }
                    if (store.FileExists(RootFolder + TestDir + @"\" + kTextReaderTestFile))
                        store.DeleteFile(RootFolder + TestDir + @"\" + kTextReaderTestFile);
                }
                PSDirectory.SetCurrentDirectory(RootFolder);
                fi = (new PSFileInfo(kTextReaderTestFile));
                using (var strmW = fi.Create())
                {
                    strmW.WriteByte(65);
                }
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var strmR = store.OpenFile(RootFolder + kTextReaderTestFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                        var line = strmR.ReadByte();
                        Assert.AreEqual(65, line, "reading created File (by 'create', written byte should match one read)");
                        Assert.AreEqual(1, strmR.Length, "CEATEd file should only have been 1 byte long");
                    }
                    if (store.FileExists(RootFolder + kTextReaderTestFile))
                        store.DeleteFile(RootFolder + kTextReaderTestFile);
                }
            }
            finally
            {
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (store.FileExists(RootFolder + TestDir + @"\" + kTextReaderTestFile))
                        store.DeleteFile(RootFolder + TestDir + @"\" + kTextReaderTestFile);
                    if (store.FileExists(RootFolder + kTextReaderTestFile))
                        store.DeleteFile(RootFolder + kTextReaderTestFile);
                }
            }
        }

        [TestMethod]
        public void Test_Appending_To_A_File()
        {
            var fi = (new PSFileInfo(RootFolder + TestFile));
            try
            {
                using (var strm = fi.AppendText())
                {
                    strm.WriteLine();
                    strm.WriteLine(TestLine1);
                }
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var strmR = new StreamReader(store.OpenFile(RootFolder + TestFile, FileMode.Open, FileAccess.Read)))
                    {
                        var OneChar = strmR.ReadLine();
                        Assert.AreEqual(1, OneChar.Length, "Should only return 1 char when reading 1st line back file after appending");
                        var line = strmR.ReadLine();
                        Assert.AreEqual(TestLine1, line, "2nd line read back should match the line written after appending texts");
                    }
                    using (var strm = store.CreateFile(RootFolder + TestDir + @"\" + TestFile))
                    {
                        strm.WriteByte(65);
                        strm.Flush();
                        strm.Close();
                    }
                }
                PSDirectory.SetCurrentDirectory(RootFolder + TestDir);
                fi = (new PSFileInfo(TestFile));
                using (var strm = fi.AppendText())
                {
                    strm.WriteLine();
                    strm.WriteLine(TestLine1);
                }
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var strmR = new StreamReader(store.OpenFile(RootFolder + TestDir + @"\" + TestFile, FileMode.Open, FileAccess.Read)))
                    {
                        var OneChar = strmR.ReadLine();
                        Assert.AreEqual(1, OneChar.Length, "Should only return 1 char when reading 1st line back file after appending in subdir");
                        var line = strmR.ReadLine();
                        Assert.AreEqual(TestLine1, line, "2nd line read back should match the line written after appending texts in subdir");
                    }
                }
            }
            finally
            {
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (store.FileExists(RootFolder + TestDir + @"\" + TestFile))
                        store.DeleteFile(RootFolder + TestDir + @"\" + TestFile);
                }
                PSDirectory.SetCurrentDirectory(@"\");
            }
        }
    }
}